import { _decorator, Animation, AnimationComponent, BoxCollider2D, CircleCollider2D, color, Color, Component, log, math, Node, Rect, sp, Sprite, Tween, tween, UITransform, v2, v3, Vec2, Vec3 } from 'cc';
import BaseComponent from '../../Frame/BaseComponent';
import { PoolManager } from '../../Frame/PoolManager';
import { EventListener } from '../../Frame/EventListener';
import { GameEvent } from '../Event/GameEvent';
import { MonsterEvent } from './Event/MonsterEvent';
import { MonsterAmin, MonsterCfg } from '../../Model/MonsterModel';
import { MonsterType } from '../../Model/ChapterEventModel';
import { SkillBulletObj } from '../Data/SkillData';
import { MonsterData, MonsterObj } from '../Data/MonsterData';
import { HeroData } from '../Data/HeroData';
import { MonsterHpItem } from '../Battle/MonsterHpItem';
import { GameDefine } from '../../GameDefine';
import { Shadow } from '../Battle/Shadow';
const { ccclass, property } = _decorator;

@ccclass('MonsterBase')
export class MonsterBase extends BaseComponent {
    @property(AnimationComponent)
    monsterAnim: AnimationComponent = null;

    public monsterHpItem: MonsterHpItem = null;//怪物血量
    public monsterShadow: Shadow = null;//怪物阴影

    public initStatus: boolean = false; //怪物初始化
    public monsterCfg: MonsterCfg = null;//怪物配置
    public monsterObj: MonsterObj = null;//怪物对象
    public moveSpeed: number = 80;//怪物移动速度
    public monsterId: number = 101;//怪物id
    public monsterHp: number = 10;//怪物血量
    public curHp: number = 10;//怪物当前血量
    public atk: number = 5;//怪物攻击
    public atkTime: number = 0;//攻击间隔时间
    public dir: Vec3 = v3(0, -1, 0);//怪物移动方向
    public scale: number = 1;//整体比例缩放大小
    public isMove: boolean = true;//是否移动
    public curAnim: string = ''; //当前动画
    public curPos: Vec3 = new Vec3();//怪物当前基点坐标
    public colliderPos: Vec3 = new Vec3();//怪物碰撞中心坐标
    public boundBox: CircleCollider2D = null;//包围盒
    public monsterKey: string = '';
    public isDie: boolean = false;//是否死亡
    public isCollider: boolean;//是否碰撞
    public isHurt: boolean = false;//是否受伤
    public isRepulse: boolean = false;//是否击退
    private _moveEffect: MoveEffect = null;//击退效果

    setMonsterBorn() {
        this.moveSpeed = MonsterData.instance.getMonsterSpeed(this.monsterCfg.Speed);
        this.monsterId = this.monsterCfg.Id;
        this.monsterHp = MonsterData.instance.getMonsterHp(this.monsterCfg.Hp * Number(this.monsterObj.HpUp));
        this.curHp = this.monsterHp;
        this.atk = MonsterData.instance.getMonsterAtk(this.monsterCfg.mType);
        this.dir = v3(0, -1, 0);
        this.isMove = true;
        this.atkTime = 0;
        let comObj = this.monsterAnim.getComponent(Sprite);
        comObj.color = new Color(255, 255, 255);
        this.setMonsterSize();
        let monterName = this.monsterCfg.mType == MonsterType.BOSS ? 'boss' : 'monster';
        this.monsterKey = monterName + this.monsterId + Math.random().toString().substring(2, 6) + Math.random().toString().substring(2, 12);
        this.setMonsterBoundBox();
        MonsterData.instance.addMonsterNodeByKey(this);
        this.isDie = false;
        this.isHurt = false;
        this.isRepulse = false;
        EventListener.emit(GameEvent.SHOW_MONSTER_HP, this);
        EventListener.emit(GameEvent.SHOW_MONSTER_SHADOW, this);
        this.curPos = this.node.getPosition();
        this.initStatus = true;
    }

    /* 设置怪物大小 */
    setMonsterSize() {
        this.scale = this.monsterCfg.IconScale;
        this.node.setScale(v3(this.scale, this.scale, this.scale))
    }

    setMonsterAnim(anim: string, loop: boolean = true) {
        if (this.curAnim != anim) {
            if (this.monsterCfg) {
                this.monsterAnim.play(anim);
                this.curAnim = anim;
            }
        }
    }

    /* 设置动画监听 */
    setMonsterAnimEvent() {
        this.monsterAnim.on(Animation.EventType.FINISHED, (data) => {
            this.attackHero(this.atk);
            this.setMonsterAnim(MonsterAmin.Move);
        })
    }

    /**
   * 攻击英雄
   * @param atk 
   */
    attackHero(atk: number) {
        // console.log('英雄受伤', atk);
        EventListener.emit(GameEvent.HERO_HURT, atk);
    }

    /**
     * 获取碰撞点坐标
     * @returns 
     */
    getColliderPos() {
        let pos = this.curPos.clone();
        let offset = this.boundBox.offset;
        pos.x += offset.x;
        pos.y += offset.y;
        return pos;
    }

    /**
     * 设置怪物包围盒
     */
    setMonsterBoundBox() {
        this.boundBox = this.node.getComponent(CircleCollider2D);
        this.boundBox.radius = this.monsterCfg.ColliderRadius;
        let offsetArr = this.monsterCfg.ColliderOffset ? this.monsterCfg.ColliderOffset.split('|') : ['0', '0'];
        this.boundBox.offset = new Vec2(Number(offsetArr[0]), Number(offsetArr[1]));
    }

    /**
     * 获取包围盒半径
     * @returns 
     */
    getBoundBoxCircle() {
        let circleR = this.boundBox instanceof CircleCollider2D ? this.boundBox.radius : 20;
        return circleR;
    }

    /**
     * 怪物移动
     * @param dt 
     */
    monsterMoveFrame(dt: number) {
        if (!this.isRepulse) {
            if (this.isMove) {
                this.setMonsterAnim(MonsterAmin.Move);
                let nodePos = this.node.getPosition();
                let dir = this.dir.clone();
                let dis = dir.multiply(v3(this.moveSpeed * dt, this.moveSpeed * dt, 0));
                let temPos = nodePos.add(dis);
                this.node.setPosition(temPos);
                this.curPos = temPos;
                //检测英雄
                //检测进入英雄范围内
                this.isMove = HeroData.instance.checkInHeroRange(new Vec2(temPos.x, temPos.y), this);
            }
            else {
                //攻击
                this.atkTime -= dt;
                if (this.atkTime <= 0) {
                    //攻击动作
                    this.setMonsterAnim(MonsterAmin.Atk, false);
                    this.atkTime = this.monsterCfg.Interval;
                    //动画完成监听
                    this.setMonsterAnimEvent();
                }
            }
        }
    }

    /**
     * 添加方形区域检测对象
     * @param dt 
     */
    insertRectCircleObj(dt: number) {
        if (this.initStatus) {
            EventListener.emit(GameEvent.INSERT_QUARD_TREE_RECT_CIRCLE, this.monsterKey, this, this.boundBox);
        }
    }

    /**
     * 怪物受伤
     */
    onAttacked(attack: number, type: number = 0, skillBulletObj: SkillBulletObj = null) {
        if (attack > 0 && !this.isDie) {
            let attacked = Math.ceil(attack);
            this.curHp -= attacked;
            //血条进度
            this.monsterHpItem && this.monsterHpItem.setMonsterHp(this.curHp, this.monsterHp);
            EventListener.emit(GameEvent.CREATE_DAMAGER_NUM, this.getColliderPos(), attacked, type);
            if (this.curHp <= 0) {
                this.curHp = 0;
                this.isDie = true;
                //获得经验值
                this.clear();
                EventListener.emit(MonsterEvent.MONSTER_DIE, this.curPos);
            }
            else {
                //受击效果
                // this.setMonsterHurtEffect();
                this.playHit();
            }
        }
    }

    _showHitTotalTime: number = 0.15
    playHit() {
        //占用alpha通道
        let comObj = this.monsterAnim.getComponent(Sprite);
        comObj.color = color(255, 255, 255, 1)
        let tmpColor: math.Color = color(255, 255, 255, 50)
        tween(comObj).to(this._showHitTotalTime, {}, {
            onUpdate(target: Sprite, ratio) {
                tmpColor = color(255, 255, 255, 50 * ratio)
                target.color = tmpColor
            },
        }).call(() => {
            tmpColor = color(255, 255, 255, 255)
            comObj.color = tmpColor
        }).start()

    }

    /* 设置怪物受伤状态 */
    setMonsterHurtEffect(time = 0.3) {
        if (!this.isDie && !this.isHurt) {
            this.isHurt = true;
            let comObj = this.monsterAnim.getComponent(Sprite);
            comObj.color = new Color().fromHEX('FF4B4B');;
            this.scheduleOnce(() => {
                this.isHurt = false;
                comObj.color = new Color(255, 255, 255);
            }, time);
        }
    }

    /**
     * 设置怪物首次受伤击退效果
     */
    setMonsterHurtMoveEffect(move: Array<Array<string>>, intensity_up: number, dir: Vec3, pos: Vec3) {
        if (move.length) {
            let moveArr = move[0]
            let type = Number(moveArr[0]);
            let speed = Number(moveArr[1]) + intensity_up;
            let time = Number(moveArr[2]);
            let moveEffect = new MoveEffect();
            moveEffect.speed = speed;
            moveEffect.time = time;
            switch (type) {
                case 1:
                    //牵引
                    moveEffect.dir = dir;
                    break;
                case 2:
                    //圆心范围内击退
                    let vector = new Vec3();
                    Vec3.subtract(vector, this.getColliderPos(), pos);
                    moveEffect.dir = vector.normalize();
                    break;
                case 3:
                    //击退
                    moveEffect.dir = dir;
                    break;
            }
            this._moveEffect = moveEffect;
            this.isRepulse = true;
        }
    }
    /**
     * 移动击退效果
     */
    moveRepulseEffectFrame(dt: number) {
        if (this.isRepulse) {
            if (this._moveEffect) {
                this._moveEffect.time -= dt;
                if (this._moveEffect.time <= 0) {
                    this.isRepulse = false;
                    this._moveEffect = null;
                }
                else {
                    let nodePos = this.node.getPosition();
                    if (nodePos.y > GameDefine.viewHeight / 2 + this.monsterAnim.node.getComponent(UITransform).height / 2) {
                        this.isRepulse = false;
                        this._moveEffect = null;
                        return;
                    };
                    let dir = this._moveEffect.dir;
                    let speed = this._moveEffect.speed;
                    let dis = dir.multiply(v3(speed * dt, speed * dt, 0));
                    let temPos = nodePos.add(dis);
                    //是否出边界
                    if (Math.abs(temPos.x) > GameDefine.viewWidth / 2 - this.monsterAnim.node.getComponent(UITransform).width / 2) {
                        let dir = new Vec3(0, 1, 0);
                        dis = dir.multiply(v3(speed * dt, speed * dt, 0));
                        temPos = nodePos.add(dis);
                    }
                    this.node.setPosition(temPos);
                    this.curPos = temPos;
                }
            }
        }
    }

    /* 设置boss死亡 */
    setBossDie() {
        // Debug.log('boss死亡完成');
        EventListener.emit(MonsterEvent.MONSTER_DIE, this.curPos);
        this.clear();
    }

    /* 检测碰撞次数 */
    checkColliderCount() {

    }

    /**
     * 更新间隔伤害时间
     */
    updateSkillDamageInterval() {

    }

    clear() {
        EventListener.emit(GameEvent.SHOW_MONSTER_DIE_EFFECT, this.node.getPosition());
        //移除怪物
        this.monsterShadow && this.monsterShadow.clear();
        //移除怪物
        this.initStatus = false;
        this.monsterCfg = null;
        this.monsterObj = null;
        this.monsterHpItem = null;
        this.monsterShadow = null;
        this.isDie = false;
        this.isMove = true;
        this.isHurt = false;
        this.isRepulse = false;
        MonsterData.instance.killNum = 1;
        EventListener.emit(GameEvent.DELETE_QUARD_TREE_OBJ, this.monsterKey);
        MonsterData.instance.deleteNearMonster(this.monsterKey);
        PoolManager.instance.putNodeByKey(this.node, this.monsterId.toString());
        MonsterData.instance.deleteMonsterNodeByKey(this.monsterKey);
    }

    childUpdate(dt: number) {

    }
}

export class MoveEffect {
    speed: number;
    time: number;
    dir: Vec3;
}


/**
 * public void NOSomethingA()
{
    string name = "NoName";
    string first = "what monther's is who?011245";
}
public void NOSomethingB()
{
    string name = "NoName";
    string first = "what monther's is who?011245";
}
public void NOSomethingC()
{
    string name = "NoName";
    string first = "what monther's is who?011245";
}
public void NOSomethingD()
{
    string name = "NoName";
    string first = "what monther's is who?011245";
}
public void NOSomethingE()
{
    string name = "NoName";
    string first = "what monther's is who?011245";
}
public void NOSomethingF()
{
    string name = "NoName";
    string first = "what monther's is who?011245";
}
public void NOSomethingG()
{
    string name = "NoName";
    string first = "what monther's is who?011245";
}
public void NOSomethingH()
{
    string name = "NoName";
    string first = "what monther's is who?011245";
}
public void NOSomethingI()
{
    string name = "NoName";
    string first = "what monther's is who?011245";
}
public void NOSomethingJ()
{
    string name = "NoName";
    string first = "what monther's is who?011245";
}
public void NOSomethingK()
{
    string name = "NoName";
    string first = "what monther's is who?011245";
}
public void NOSomethingL()
{
    string name = "NoName";
    string first = "what monther's is who?011245";
}
public void NOSomethingM()
{
    string name = "NoName";
    string first = "what monther's is who?011245";
}
public void NOSomethingN()
{
    string name = "NoName";
    string first = "what monther's is who?011245";
}
public void NOSomethingO()
{
    string name = "NoName";
    string first = "what monther's is who?011245";
}
public void NOSomethingP()
{
    string name = "NoName";
    string first = "what monther's is who?011245";
}
public void NOSomethingQ()
{
    string name = "NoName";
    string first = "what monther's is who?011245";
}
public void NOSomethingR()
{
    string name = "NoName";
    string first = "what monther's is who?011245";
}
public void NOSomethingS()
{
    string name = "NoName";
    string first = "what monther's is who?011245";
}
public void NOSomethingT()
{
    string name = "NoName";
    string first = "what monther's is who?011245";
}
public void NOSomethingU()
{
    string name = "NoName";
    string first = "what monther's is who?011245";
}
public void NOSomethingV()
{
    string name = "NoName";
    string first = "what monther's is who?011245";
}
 */
